package chapter_10


abstract class Element {
  // 具有抽象成员的类本身必须被声明为抽象的，只要在class前加上abstract修饰符即可
  def contents: Array[String]
  def width: Int = contents(0).length
  def height: Int = contents.length

  // 实现above、beside和toString
  def above(that: Element): Element = {
    val this1 = this widen that.width
    val that1 = that widen this.width
    Element.elem(this1.contents ++ that1.contents)
  }

  def beside(that: Element): Element = {
    val this1 = this heighten that.height
    val that1 = that heighten that.height
    Element.elem(
      for ((line1, line2) <- this1.contents zip that1.contents)
        yield line1 + line2
    )
  }

  // 变高变宽
  def widen(w: Int): Element =
    if (w <= width) this
    else {
      val left = Element.elem(' ', (w - width) / 2, height)
      var right = Element.elem(' ', w - width - left.width, height)
      left beside this beside right
    }

  def heighten(h: Int): Element =
    if (h < height) this
    else {
      val top = Element.elem(' ', width, (h - height) / 2)
      var bot = Element.elem(' ', width, h - height - top.height)
      top above this above bot
    }

  override def toString = contents mkString "\n"
}


object Element {

  // 同时定义同名的参数的一个简写方式
  private class ArrayElement(val contents: Array[String]) extends Element
  //class ArrayElement(conts: Array[String]) extends Element {
  //  override def contents = conts
  //}

  private class LineElement(s: String) extends Element {
    val contents = Array(s)
    override def width = s.length
    override def height = 1
  }

  private class UniformElement (
                                 ch: Char,
                                 override val width: Int,
                                 override val height: Int
                               ) extends Element {
    private val line = ch.toString * width
//    def contents = Array.make(height, line)
    def contents = Array.fill(height)(line)
  }

  // 定义工厂对象
  def elem(contents: Array[String]): Element =
    new ArrayElement(contents)

  def elem(chr: Char, width: Int, height: Int): Element =
    new UniformElement(chr, width, height)

  def elem(line: String): Element =
    new LineElement(line)
}


///////////////////////////////////////////////////////////////////
//class Cat {
//  val dangerous = false
//}
//
//
//class Tiger (
//            // Tiger2的简写
//            override val dangerous: Boolean,
//            private var age: Int
//            ) extends Cat
//
//
//class Tiger2 (param1: Boolean, param2: Int) extends Cat {
//  override val dangerous: Boolean = param1
//  private var age = param2
//}
///////////////////////////////////////////////////////////////////


object chapter_10 {
  // 画出给定数量边界的螺旋
  val space = Element.elem(" ")
  val corner = Element.elem("+")

  def spiral(nEdges: Int, direction: Int): Element = {
    if (nEdges == 1)
      Element.elem("+")
    else {
      val sp = spiral(nEdges - 1, (direction + 3) % 4)
      def verticalBar = Element.elem('|', 1, sp.height)
      def horizontalBar = Element.elem('-', sp.width, 1)
      if (direction == 0)
        (corner beside horizontalBar) above (sp beside space)
      else if (direction == 1)
        (sp above space) beside (corner above verticalBar)
      else if (direction == 2)
        (space beside sp) above (horizontalBar beside corner)
      else
        (verticalBar above corner) beside (space above sp)
    }
  }

  def main(args: Array[String]): Unit = {
//    val nSiders = 6
    val nSiders = 11
//    val nSiders = 17
    println(spiral(nSiders, 0))
  }
}
